#include <iostream>
#include <unistd.h>
#include<vector>
#include<sys/wait.h>
#include<sys/types.h>
#include"Task.hpp"

class channle{
public:
    channle(pid_t pid,std::string name,int wfd)
    :_pid(pid)
    ,_string_processname(name)
    ,_wfd(wfd)
    {}
    pid_t getpid(){
        return _pid;
    }
    int getwfd(){
        return _wfd;
    }
    std::string getname(){
        return _string_processname;
    }
    void Wait(){
        int status = 0;
        pid_t rid = waitpid(0,&status,0);
        if(rid > 0){
            std::cerr <<"Process ID:"<<_pid<< "    wait success" << std::endl;
            std::cerr << "exit sig:" << (status & 0x7F) << std::endl;
            std::cerr << "exit code:" << ((status >> 8) & 0xFF) << std::endl;
        }
    }
    void CloseChannel(){
        close(_wfd);
    }

private:
    pid_t _pid;
    std::string _string_processname;
    int _wfd;//信道是每次pipe打开的,文件fd不是0，1，会依次占用最小值
};


void CreateChannleAndSub(std::vector<channle> &channles,int num){
    for (int i = 0; i < num; i++)
    {
        //分配信道
        int pipefd[2];
        int n = pipe(pipefd);
        if(n<0)
            exit(1);
        //进程打开
        pid_t id = fork();
        
        if(id == 0){
            close(pipefd[1]);
            work(pipefd[0]);
            exit(0);
        }
        std::string name = "Channle-" + std::to_string(i);
        channles.push_back(channle(id, name, pipefd[1]));//保存的是管道的写方式fd
        close(pipefd[0]);
    }
}
int NextChannle(int channlesize){
    static int next = 0;
    int channle = next % channlesize;
    next++;
    return channle;
}
void CtrlProcessOnce(std::vector<channle> &channles){
    int taskindex = SelectTask();
    int channleindex = NextChannle(channles.size());
    write(channles[channleindex].getwfd(), &taskindex, sizeof(taskindex));
    std::cout << "taskcommand: " << taskindex << " channel: "
              << channles[channleindex].getname() << " sub process: " 
              << channles[channleindex].getpid() << std::endl;
}
void CtrlProcess(std::vector<channle>& channles,int times = -1){
    if(times > 0){
        while(times--){
            sleep(1);
            CtrlProcessOnce(channles);
        }
    }
    else{
        while(true){
            sleep(1);
            CtrlProcessOnce(channles);
        }
    }
}
//        bug 匿名管道的继承问题
void CleanChannel(std::vector<channle>& channels){
    //倒着关
    int num = channels.size();
    while(num--){
        channels[num].CloseChannel();
        sleep(3);
        channels[num].Wait();
    }
    // for (auto &channel : channels)
    // {
    //     channel.CloseChannel();
    //     sleep(3);
    //     channel.Wait();
    // }
    // for(auto& channel:channels){
    //     channel.Wait();
    // }
}
int main(int argc, char *argv[])
{
    // 应该是没有给个数
    if (argc != 2)
    {
        std::cerr << "Usage:" << argv[0] << "processnum" << std::endl;
        return 1;
    }
    int num = std::stoi(argv[1]); // 应该是进程池的进程个数
    std::cout << "任务个数:" << num << std::endl;
    std::vector<channle> channels;
    //1.创建信道和子进程
    CreateChannleAndSub(channels,num);
    
    // 2.通过channle管理子进程
    CtrlProcess(channels,num);

    // 3.回收管道和子进程
    CleanChannel(channels);

    sleep(10);//观察僵尸进程
}